/******************************************************************************\
*                                                                              *
*     File: TestSet_output_cli.cc                                              *
*                                                                              *
*   Author: Douwe A. van Twillert                                              *
*  Purpose: Generates output for the TestSet unit test framework,              *
*           in this case for the command line interface                        *
*  Version: 1.0      TWI 20070315                                              *
*           - Initial version                                                  *
*  Version: 1.0.1    AKK 20070322                                              *
*           - TestSet_output_not_reached_failed(...) added                     *
*  Version: 1.0.2    TWI 20070323                                              *
*           - Changed all tabs to spaces                                       *
*           - Made versioning comments consistent                              *
*  Version: 1.1       TWI 20080221                                             *
*           - reformatted to make prints easier to read and for consistency    *
*  Version: 1.11      TWI 20080320                                             *
*           - flushed all outputs (also C++ streams) for better output         *
*  Version: 1.2      TWI 20080603                                              *
*           - output added for setup and setup once                            *
*                                                                              *
\******************************************************************************/


/*
 *  System Includes
 */
#include "devcpp.h"
#include <stdio.h>
#ifdef __cplusplus
  #include <iostream>
#endif
/*
 *  Module includes
 */
#include "TestSet.hpp"
#include "TestSet_output.hpp"

/*
 *  Module defines
 */

/*
 *  Module typedefinitions
 */

/*
 *  Module Global data
 */
static const char passed[8] = "passed";
static const char failed[8] = "failed";



/*
 *  TestSet_output_flush_all() : flush output before each testframework output
 */
void TestSet_output_flush_all()
{
#ifdef __cplusplus
    std::cerr << std::flush;
#endif
    (void) fflush(stderr);
#ifdef __cplusplus
    std::cout << std::flush;
#endif
    (void) fflush(stdout);
 }


/*
 *  TestSet_output_all_test_sets_before() : flush output before all test sets
 */
extern void TestSet_output_all_test_sets_before(int nr_of_sets)
{
	TestSet_output_flush_all();
}


/*
 * TestSet_output_all_test_sets_after(): flush output after all test sets
 */
extern void TestSet_output_all_test_sets_after(int passed, int failed,
                                               int total, int nr_of_test_sets)

/*
 *  Description : Shows the output just after executing a test case
 *
 *  Input(s)    : passed         - nr of passed test cases in the test set
 *                failed         - nr of failed test cases in the test set
 *                nr_of_tests    - nr of test cases in the test set
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "\n\nExecuted %d test cases of %d test sets\n",
                           total, nr_of_test_sets);
    (void) fprintf(stdout, "    passed = %5d\n    failed = %5d\n"
                           "    -------------- +\n     total = %5d\n",
                           passed, failed, total);
    (void) fflush(stdout);
}


/*#----------------------------------------------------------------------#*/
extern void TestSet_output_test_set_before(const char* test_set_name,
                                           int nr_of_tests)

/*
 *  Description : Execute the current test case

 *  Input(s)    : test_set_name  - name of the test set
 *                nr_of_tests    - nr of test cases in the test set
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "  Executing test set %s with %d testcases\n",
                           test_set_name?test_set_name:"<null>", nr_of_tests);
    (void) fflush(stdout);
}


/*#----------------------------------------------------------------------#*/
extern void TestSet_output_test_set_after(const char* test_set_name, int passed,
                                          int failed, int nr_of_tests)

/*
 *  Description : Shows the output just after executing a test case
 *
 *  Input(s)    : test_set_name  - name of the test set
 *                passed         - nr of passed test cases in the test set
 *                failed         - nr of failed test cases in the test set
 *                nr_of_tests    - nr of test cases in the test set
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "\n  Executed %d test cases of test set %s\n",
                           nr_of_tests, test_set_name ? test_set_name : "<null>");
    (void) fprintf(stdout, "    passed = %5d\n    failed = %5d\n"
                           "    -------------- +\n     total = %5d\n",
                           passed, failed, nr_of_tests);
    (void) fflush(stdout);
}



/*#----------------------------------------------------------------------#*/
void TestSet_output_test_case_before( const char* test_case_name )

/*
 *  Description : Execute the current test case

 *  Input(s)    : test_case_name - name of the test case to be executed
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "    Executing test %s ... ",
                           test_case_name ? test_case_name : "<null>");
    (void) fflush(stdout);
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_test_case_after(const char*, bool test_result)

/*
 *  Description : Shows the output just after executing a test case
 *
 *  Input(s)    : test_case_name - name of the currently executed test case
 *
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "%s\n", (test_result == OK) ? passed : failed);
    (void) fflush(stdout);
}


/*#----------------------------------------------------------------------#*/
extern void TestSet_output_verification_failed(const char* file, int linenr,
                                               const char* expression)

/*
 *  Description : Shows the output for a failed verification inside a test case

 *  Input(s)    : file       - name of the file of the failed verify statement
 *                line_nr    - line number of the failed verify statement
 *                expression - the expression which failed
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       :
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */


/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stderr, "<%s>[%d]: Verification of '%s' failed\n", file,
                           linenr, expression ? expression : "<null!>");
    (void) fflush(stderr);
}

/*#----------------------------------------------------------------------#*/
extern void TestSet_output_setup_once_failed(const char* test_set_name)
/*
 *  Description : Shows the output for a failed verification inside a test case

 *  Input(s)    : test_set_name - name of the test set to be executed
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       :
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */


/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "    !!!! Setup *once* for test set '%s' failed !!!!\n",
                           test_set_name ? test_set_name : "<null>");
    (void) fflush(stderr);
}

/*#----------------------------------------------------------------------#*/
extern void TestSet_output_setup_failed(const char* test_case_name)
/*
 *  Description : Shows the output for a failed verification inside a test case

 *  Input(s)    : test_case_name - name of the test case to be executed
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       :
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */


/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stdout, "    !!!! Setup for test case '%s' failed !!!!\n",
                           test_case_name ? test_case_name : "<null>");
    (void) fflush(stderr);
}

/*#----------------------------------------------------------------------#*/
// AKK 20070322 added to complement the NOT_REACHED clause in a testset
extern void TestSet_output_not_reached_failed(const char * file, int linenr)

/*
 *  Description : Reports code reached that should not be reached

 *  Input(s)    : file       - name of the file that should not have been reached
 *                line_nr    - line number that should not have been reached
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       :
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stderr, "<%s>[%d]: testcode declared not_reached was reached\n", file,
                           linenr);
    (void) fflush(stderr);
}

// AKK - END
/*#----------------------------------------------------------------------#*/
void TestSet_output_expect_signal(int a_signal_nr)

/*
 *  Description : Shows the output for a to be expected signal

 *  Input(s)    : signal_nr - the number of the signal that is expected
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    fprintf(stderr, "Expecting signal: %d", a_signal_nr);
    fflush(stderr);
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_expect_assertion_failed()

/*
 *  Description : Shows the output for a to be expected signal

 *  Input(s)    : -
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */



/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    fprintf(stderr, "Expecting an assertion failed\n\t");
    fflush(stderr);
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_handle_unexpected_signal(int a_signal)

/*
 *  Description : Shows the output just before executing test case

 *  Input(s)    : test_case_name - name of the test case with an unhandled
 *                                 exception
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stderr, "\n\tUnexpected signal caught (%d)\n", a_signal );
    // AKK 20070322 - added
    psignal( a_signal, "\tMNEMONIC IS " );        // op stderr
    // AKK - END
    (void) fflush(stderr);
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_unhandled_exception( const char* test_case_name,
		                                 const char* probable_cause )

/*
 *  Description : Shows the output just before executing test case

 *  Input(s)    : test_case_name - name of the test case with an unhandled
 *                                 exception
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf( stderr, "Unhandled exception '%s' in test case '%s', aborting\n",
    		        probable_cause ? probable_cause : "<no cause given>",
					test_case_name ? test_case_name : "<no name>"
				  );
    (void) fflush( stderr );
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_ensure(const char* file, int linenr, const char* function,
                           const char* condition)

/*
 *  Description : Execute the current test case

 *  Input(s)    : test_case_name
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       :
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stderr, "<%s>[%d] %s: %s failed, aborting\n", file, linenr,
                           function, condition);
    (void) fflush(stderr);
}


/*#----------------------------------------------------------------------#*/
void TestSet_output_magic(const char* file,
                          int linenr,
                          const char* function,
                          const char* kind,
                          unsigned int set_magic,
                          unsigned int expected_magic)

/*
 *  Description : Execute the current test case

 *  Input(s)    : test_case_name
 *  Output(s)   : -
 *  Returns     : -
 *  Notes       : -
 *  Pre.Cond.   : -
 *  Post.Cond.  : -
 *
 */

/*#----------------------------------------------------------------------#*/
{
	TestSet_output_flush_all();
    (void) fprintf(stderr, "<%s>[%d] %s: Test%s magic value corrupted (0x%x"
                           " != 0x%x), aborting\n", file, linenr, function,
                           kind, set_magic, expected_magic);
    (void) fflush(stderr);
}


